﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="FileReportRepository.cs" company="Collaboris Ltd.">
//   Copyright (c) Collaboris Ltd. All rights Reserved.
// </copyright>
// <summary>
//   The file system report repository.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Collaboris.Saf.Repositories
{
    using System;
    using System.IO;

    using Engine.Report;

    using Utils;

    /// <summary>
    /// Saves\retrieves a <see cref="MacroReport"/> to\from  from the Filesystem
    /// <remarks>
    /// Automatically appends a counter to the report filename if the file already exists. 
    /// It allways returns the last report saved.
    /// </remarks>
    /// </summary>
    public class FileReportRepository : FileRepository<MacroReport>
    {
        #region Constants and Fields

        /// <summary>
        /// The directory where the report will be stored.
        /// </summary>
        private string reportDirectory;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="FileReportRepository"/> class.
        /// </summary>
        /// <param name="reportDirectory">
        /// The root folder.
        /// </param>
        /// <param name="fileName">
        /// The file Name.
        /// </param>
        public FileReportRepository(string reportDirectory)
        {
            ValidationHelper.VerifyStringArgument(reportDirectory, "rootFolder");
            //ValidationHelper.VerifyStringArgument(fileName, "macroFileName");

            this.reportDirectory = reportDirectory;
            //this.fileName = fileName;
        }

        #endregion

        #region Helper Methods

        /// <summary>
        /// The get file name.
        /// </summary>
        /// <param name="name">
        /// The name.
        /// </param>
        /// <param name="action">
        /// The action.
        /// </param>
        /// <param name="report">
        /// The report.
        /// </param>
        /// <returns>
        /// The get file name.
        /// </returns>
        protected override string GetFileName(string name, RepositoryAction action, MacroReport report)
        {
            switch (action)
            {
                case RepositoryAction.save:
                    return this.GetNextFreeFileName(this.GetReportNameWithPath(name), 0);

                case RepositoryAction.load:
                    return this.GetMostRecentReportNameFromPath(name);
            }

            return null;
        }

        /// <summary>
        /// This will try and locate the most recent file matching the mode
        /// from the Report Path.
        /// </summary>
        /// <param name="fileName">
        /// The file Name.
        /// </param>
        /// <returns>
        /// The get most recent report name from path.
        /// </returns>
        private string GetMostRecentReportNameFromPath(string fileName)
        {
            ValidationHelper.VerifyStringArgument(fileName, "fileName");

            int dotIndex = fileName.LastIndexOf(".");
            if (dotIndex == -1)
                dotIndex = fileName.Length;

            string pattern = fileName.Insert(dotIndex, "*");
            string[] allReports = Directory.GetFiles(this.reportDirectory, pattern);
            DateTime lastAccessTime = DateTime.MinValue;
            string latestFileName = string.Empty;

            for (int i = 0; i < allReports.Length; i++)
            {
                string currentFileName = allReports[i];
                DateTime currentAccessTime = File.GetLastAccessTime(currentFileName);

                if (currentAccessTime > lastAccessTime)
                {
                    lastAccessTime = currentAccessTime;
                    latestFileName = currentFileName;
                }
            }

            return latestFileName;
        }

        /// <summary>
        /// Gets the name of the next available file name.
        /// </summary>
        /// <remarks>
        /// If a file called "macro1.do" already exists on disk
        /// this method will generate a "mymacro.macro [1]"
        /// </remarks>
        /// <param name="fileName">
        /// Name of the file.
        /// </param>
        /// <param name="version">
        /// The version.
        /// </param>
        /// <returns>
        /// The get next free file name.
        /// </returns>
        private string GetNextFreeFileName(string fileName, int version)
        {
            string fileNameToCheck;
            if (version == 0)
            {
                fileNameToCheck = fileName;
            }
            else
            {
                int extPosition = fileName.LastIndexOf(".");
                fileNameToCheck = fileName.Insert(extPosition, " [" + version + "]");
            }

            if (!File.Exists(fileNameToCheck))
            {
                return fileNameToCheck;
            }

            version = version + 1;
            return this.GetNextFreeFileName(fileName, version);
        }

        /// <summary>
        /// Gets the full name of the file.
        /// </summary>
        /// <param name="mode">
        /// The mode.
        /// </param>
        /// <returns>
        /// The get report name with path.
        /// </returns>
        private string GetReportNameWithPath(string fileName)
        {
            return Path.Combine(this.reportDirectory, fileName);
        }

        #endregion
    }
}